// Shared Resource
// (c) jimon game studio

#ifndef JEH_JESHAREDRESOURCE
#define JEH_JESHAREDRESOURCE

#include "jeStl.h"
#include "IResource.h"

namespace je
{
	namespace media
	{
		//! Shared Resource Interface
		class ISharedResource:public je::jeUnknown
		{
		public:
			//! Destructor
			virtual ~ISharedResource()
			{
			}

			//! Get Resource Name
			virtual const jeStringc & GetResourceName() = 0;
		};

		//! Shared Resource Container
		template <typename KeyType>
		class jeSharedResourceManager
		{
		protected:
			typedef jeMap<KeyType,ISharedResource*> SharedMapType;
			SharedMapType SharedMap;
		public:
			//! Constructor
			jeSharedResourceManager()
			{
			}

			//! Destructor
			~jeSharedResourceManager()
			{
				for(typename SharedMapType::Iterator Iter = SharedMap.getIterator();!Iter.atEnd();Iter++)
					Iter->getValue()->Drop();
				SharedMap.clear();
			}

			//! Get Resource
			ISharedResource * GetResource(KeyType Key,u1 GrabResource = true)
			{
				typename SharedMapType::Node * Node = SharedMap.find(Key);
				if(Node)
				{
					if(GrabResource)
						Node->getValue()->Grab();
					return Node->getValue();
				}
				else
					return NULL;
			}

			//! Add Resource
			void AddResource(KeyType Key,ISharedResource * Resource)
			{
				SharedMap.set(Key,Resource);
			}

			//! Drop Resource
			void DropResource(KeyType Key,ISharedResource * Resource)
			{
				if(Resource && Resource->Drop())
					SharedMap.remove(Key);
			}

			//! Drop Resource
			void DropResource(KeyType Key)
			{
				DropResource(Key,GetResource(Key,false));
			}
		};

		typedef jeSharedResourceManager<void*> jeSharedResourceManagerUniversal;
	}
}

#define JE_RESOURCEBASE_SHARED_GRAB( __Var, __Res, __Key, __Key2, __Type)	{__Var = static_cast<je::media::jeShared##__Type*>(__Res->GetSharedManager()->GetResource(__Key));\
																	if(!__Var){\
																		je::media::jeShared##__Type * __Temp##__Type = NULL;\
																		JENEW(__Temp##__Type,media::jeShared##__Type(__Res,__Key2))\
																		__Var = static_cast<je::media::jeShared##__Type*>(__Temp##__Type);\
																		__Res->GetSharedManager()->AddResource(__Key,__Var);}}
#define JE_RESOURCEBASE_SHARED_GRAB_FREEKEY( __Var, __Res, __Key, __Key2, __Type) \
																	{__Var = static_cast<je::media::jeShared##__Type*>(__Res->GetSharedManager()->GetResource(__Key));\
																	if(!__Var){\
																		je::media::jeShared##__Type * __Temp##__Type = NULL;\
																		JENEW(__Temp##__Type,media::jeShared##__Type __Key2 )\
																		__Var = static_cast<je::media::jeShared##__Type*>(__Temp##__Type);\
																		__Res->GetSharedManager()->AddResource(__Key,__Var);}}
#define JE_RESOURCEBASE_SHARED_DROP(__Var,__Key,__Type)	{if(__Var) {JE_RESOURCEBASE_GET(__Var->GetResourceName(),__Type)->GetSharedManager()->DropResource(__Key);}}


#endif
